home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: initializeThreads.c,v $
- * $Revision: 1.2 $
- * $Date: 1996/05/04 23:51:55 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
- #include "sysdefs.h"
-
- #ifdef mips
- # include <mips/param.h>
- # include <mips/vmparam.h>
- #elif defined(sparc)
- # include <machine/param.h>
- # include <machine/vmparam.h>
- #elif defined(_AIX)
- # include <sys/pseg.h>
- # undef n_name /* nlist.h messes this up */
- #elif defined(hpux)
- # include <sys/param.h>
- # include <sys/vmparam.h>
- # include <sys/user.h>
- #elif defined(linux)
- # include <sys/param.h>
- # include <sys/user.h>
- #elif !(defined(mips) || defined(sparc) || defined(_AIX) || defined(hpux) || defined(linux))
- not supported
- #else
- /* this else should have the not supported code, but the
- ultrix cpp is broken */
- #endif
-
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "thread_funcs.h"
- #include "thread_globals.h"
- #include "ips_support.h"
-
- #ifdef linux
- /*
- This routine is required to force the allocation of stack pages to our
- process. Attempting to access pages below the current SP causes a
- access violation in Linux.
- */
- void touchStack(int nBytes)
- {
- char someSpace[1024];
-
- if (nBytes > 1024)
- touchStack(nBytes-1024);
- }
-
- #endif linux
- /*
- * This function initializes threads and their stacks.
- *
- * The macro NBPG used in the following code is the number
- * of bytes per VM page (defined in /usr/include/machine/param.h
- */
-
- static int StackSize = 0;
-
- void
- initializeThreads (
- register FOUR stackSize,
- PFI procedure
- )
- {
- FOUR numThreads = NumThreads; /* from initializeEnv() */
- TCB *tcb;
- FOUR *sp;
- FOUR j;
- int i;
- int stackLoc = (int) &(stackLoc); /* integer address of stack location */
-
- /*
- * DEBUG_THREAD can be defined to allow extra stack space to
- * track down bugs related to stack corruption.
- */
- #ifdef DEBUG_THREAD
- ExtraStackSpace = NBPG;
- #else
- ExtraStackSpace = 0;
- #endif
-
- #ifdef DEBUG
- StackSize = stackSize;
- #endif DEBUG
-
- #ifdef linux
- /*
- Allocate stack pages before initializeTcb starts poking around in memory
- below the current SP.
- */
- touchStack((numThreads+4)*(stackSize+ExtraStackSpace)*sizeof(FOUR));
- #endif
-
- TRPRINT(TR_THREAD, TR_LEVEL_1, ("numThreads:%d, stackSize:%d", numThreads, stackSize));
-
- /*
- * initialize the free list and the ready list, and the
- * waiting list for thread forks
- */
- initializeList( &FreeList );
- initializeList( &ReadyList );
- initializeList( &ThreadForkWaitList );
-
- /*
- * allocate space for tcbs
- */
- if ((Tcbs = (TCB *) malloc((unsigned int) (numThreads * sizeof(TCB)))) == NULL) {
-
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- }
-
- /*
- * allocate space for stacks on the stack
- *
- */
- #ifdef hpux
- /* stacks on the HP's grow up!!! So start farther up */
- sp = (FOUR *) (((stackLoc + NBPG) & ~0x7)+(stackSize+ExtraStackSpace));
-
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- sp = (FOUR *) (((stackLoc - NBPG) & ~0x7)-(stackSize+ExtraStackSpace));
-
- /* sp = (FOUR *) ((USRSTACK - NBPG) & ~0x7); */
-
- #else
- not supported
- #endif
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("sp:%x", sp));
-
- tcb = Tcbs;
- #ifdef IPS_SUPPORT
- IPSinitThread();
- #endif IPS_SUPPORT
-
- /*
- * initialize all the threads
- */
- #ifdef hpux
- /* stacks on the HP's grow up!!! */
- # define OP_DIR +=
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- /* stacks grow down */
- # define OP_DIR -=
- #else
- not supported
- #endif
- for (i = 0; i < numThreads; i++, tcb++, sp OP_DIR (stackSize+ExtraStackSpace)) {
-
- tcb->id = i;
-
- initializeTcb(procedure, tcb, sp, (stackSize+ExtraStackSpace));
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("tcb:%i loc:%x stack:%x SP:%x",
- tcb->id, tcb, tcb->stack, tcb->sp));
-
- /*
- * put the thread on the free queue
- */
- listEnq( &FreeList, &(tcb->controlList) );
- }
-
- /*
- * mark the stack areas so that the usage patterns can
- * be monitored to check adequacy of stack sizes
- */
- #ifdef hpux
- /* stacks on the HP's grow up!!! So go the other way */
- sp = (FOUR *) (((stackLoc + NBPG) & ~0x7)+(stackSize+ExtraStackSpace));
- for (i = 0; i < numThreads; i++)
- {
- /*
- * don't blow away the initialized part
- */
- sp += USEDSTACK;
-
- for (j = USEDSTACK; j < (stackSize+ExtraStackSpace); j++, sp++) {
-
- *sp = STACKPATTERN;
- }
- }
-
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
-
- sp = (FOUR *) (((stackLoc - NBPG) & ~0x7)-(stackSize+ExtraStackSpace));
- for (i = 0; i < numThreads; i++) {
-
- /*
- * don't blow away the initialized part
- */
- sp -= USEDSTACK;
-
- for (j = USEDSTACK; j < (stackSize+ExtraStackSpace); j++, sp--) {
-
- *sp = STACKPATTERN;
- }
- }
- #else
- not supported
- #endif
-
- /*
- * take a thread off the free list to use for
- * a spare in case of congestion
- */
- Spare = (TCB *) listDeq( &FreeList );
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("Spare:%x id:%d", Spare, Spare->id));
-
- /*
- * take from the free list a thread to run.
- */
- Active = (TCB *) listDeq( &FreeList );
- TRPRINT(TR_THREAD, TR_LEVEL_2, ("Active:%x id:%d", Active, Active->id));
- }
-
- void
- freeThread(TCB *thread)
- {
- reinitTcb(thread); /* clean it up before putting it on the FreeList */
- listEnq( &FreeList, &(thread->controlList) );
- notify(&ThreadForkWaitList, esmNOERROR, esmNOERROR);
- }
-
- void
- checkStacks()
- {
- TCB *tcb = Tcbs;
- FOUR *sp;
- int i, j;
-
- for (i = 0, tcb = Tcbs; i < NumThreads; i++, tcb++) {
- #ifdef hpux
- /* stack grows up */
- /* check stack[StackSize+ExtraStackSpace] down to stack[StackSize] */
- sp = tcb->stack + StackSize + ExtraStackSpace;
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- /* stack grows down */
- /* check stack[-(StackSize+ExtraStackSpace] up to stack[-StackSize] */
- sp = tcb->stack - (StackSize + ExtraStackSpace);
- #else
- not supported
- #endif
- /*
- fprintf(stderr, "Checking tcb %d, %d words from 0x%x to 0x%x\n",
- tcb->id, ExtraStackSpace-1,
- &sp[1], &sp[ExtraStackSpace-1]);
- */
- for(j=1; j< (ExtraStackSpace + 100); j++) {
- FOUR *place =
- #ifdef hpux
- &sp[-j];
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- &sp[j] ;
- #else
- not supported
- #endif
-
- if( *place != STACKPATTERN ) {
- fprintf(stderr,
- "tcb %d,state %d (stack @0x%x): loc 0x%x(%d) trashed: 0x%x\n",
- tcb->id, tcb->state, tcb->stack,
- place,
- #ifdef hpux
- -j,
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- j,
- #else
- not supported
- #endif
- *place);
- SM_ERROR(TYPE_SYS, esmINTERNAL);
- }
- }
- }
- }
-
- int LargestStack = 0;
-
- void
- checkMyStack()
- {
- TCB *tcb = Active;
- FOUR *current;
-
- /* DO NOT PUT ANY SM_ASSERTS IN THIS FUNCTION!!!!!!!!!!*/
-
- #ifdef hpux
- #define ABOVE <
- #define BELOW >
- #define END_STACK(s) ((s) + StackSize)
- #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
- #define ABOVE >
- #define BELOW <
- #define END_STACK(s) ((s) - StackSize)
- #else
- not supported
- #endif
-
- current = (FOUR *)(&tcb);
- if( (current ABOVE tcb->stack) ||
- (current BELOW END_STACK(tcb->stack))
- ) {
- fprintf(stderr,
- "STACK OVERFLOW FOR tcb %d!\n", tcb->id);
- SM_ERROR(TYPE_SYS, esmINTERNAL);
- } else {
- int diff;
-
- diff = current - tcb->stack;
- if(diff < 0)
- diff = 0-diff;
-
- if(diff > LargestStack)
- LargestStack = diff;
- }
- }
-
- #ifdef DEBUG
- int
- SanityCheck()
- {
- /* DO NOT PUT ANY SM_ASSERTS IN THIS FUNCTION!!!!!!!!!!*/
- if(InitializationCompleted)
- checkMyStack();
- return 0;
- }
- #endif DEBUG
-
-